package de.hsmannheim.poolraumapp.fragment;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Observable;
import java.util.Observer;
import java.util.Set;

import org.apache.commons.lang3.StringUtils;
import org.joda.time.format.DateTimeFormat;

import android.app.Activity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.ListView;
import de.hsmannheim.poolraumapp.R;
import de.hsmannheim.poolraumapp.model.RoomQuery;
import de.hsmannheim.poolraumapp.model.RoomQuery.What;
import de.hsmannheim.poolraumapp.model.RoomQuery.WhatOS;

/**
 * A list fragment representing a list of Items. This fragment also supports
 * tablet devices by allowing list items to be given an 'activated' state upon
 * selection. This helps indicate which item is currently being viewed in a
 * {@link WhenFragment}.
 * <p>
 * Activities containing this fragment MUST implement the {@link NavigationListener}
 * interface.
 */
public class NavigationFragment extends PoolraumFragment implements Observer, OnClickListener {

	private static final String TAG = NavigationFragment.class.getName();
	
	/**
	 * The serialization (saved instance state) Bundle key representing the
	 * activated item position. Only used on tablets.
	 */
	private static final String STATE_SELECTED_ITEM = "selected_item";

	/**
	 * The fragment's current callback object, which is notified of list item
	 * clicks.
	 */
	private NavigationListener listener = DUMMY_LISTENER;

	/**
	 * The current activated item position. Only used on tablets.
	 */
	private int selectedItem = ListView.INVALID_POSITION;

	private boolean twoPane;

	public static final String NAVIGATION_WHEN = "when";
	public static final String NAVIGATION_WHERE = "where";
	public static final String NAVIGATION_WHAT = "what";
	public static final String NAVIGATION_RESULTS = "results";
	
	public static final String NAVIGATION_TITLE_QUERY = "title_query";
	public static final String NAVIGATION_TITLE_RESULTS = "title_results";		
	
	/**
	 * A callback interface that all activities containing this fragment must
	 * implement. This mechanism allows activities to be notified of item
	 * selections.
	 */
	public interface NavigationListener {
		/**
		 * Callback for when an item has been selected.
		 */
		public void onNavigateToDetail(String id);
	}

	/**
	 * A dummy implementation of the {@link NavigationListener} interface that does
	 * nothing. Used only when this fragment is not attached to an activity.
	 */
	private static final NavigationListener DUMMY_LISTENER = new NavigationListener() {
		@Override
		public void onNavigateToDetail(String id) {
		}
	};

	@Override
	public View onCreateView(LayoutInflater inflater, ViewGroup container,
			Bundle savedInstanceState) {	
		View view = inflater.inflate(R.layout.fragment_navigation, container, false);
		
		Button whenButton = setButtonText(view, R.id.navigation_when_button, getWhen());
		whenButton.setOnClickListener(this);
		
		Button whereButton = setButtonText(view, R.id.navigation_where_button, getWhere());
		whereButton.setOnClickListener(this);
		
		Button whatButton = setButtonText(view, R.id.navigation_what_button, getWhat());
		whatButton.setOnClickListener(this);
		
		Button resultsButton = setButtonText(view, R.id.navigation_results_button, getResults());
		resultsButton.setOnClickListener(this);
		
		getRoomQuery().addObserver(this);
		
		return view;
	}
	

	private String getWhen() {
		RoomQuery roomQuery = getRoomQuery();
		StringBuilder when = new StringBuilder(getResources().getString(R.string.navigation_when));
		when.append(": ");
		switch (roomQuery.getDay()) {
			case TODAY:
				when.append(getResources().getString(R.string.when_day_today));
				break;
			case WEEKDAY:
				when.append(getResources().getStringArray(R.array.when_day_weekdays)[roomQuery.getWeekday() - 1]);
				break;
			case DATE:
				when.append(DateTimeFormat.forStyle("M-").withLocale(Locale.getDefault()).print(roomQuery.getDate()));
		}
		when.append(" (");
		switch (roomQuery.getTime()) {
			case NOW:
				when.append(getResources().getString(R.string.when_time_now));
				break;
			case POINT:
				when.append(DateTimeFormat.forStyle("-S").withLocale(Locale.getDefault()).print(roomQuery.getTimePoint()));
				break;
			case SPAN:
				when.append(DateTimeFormat.forStyle("-S").withLocale(Locale.getDefault()).print(roomQuery.getFrom()));
				when.append(' ');
				when.append(getResources().getString(R.string.when_time_span_to));
				when.append(' ');
				when.append(DateTimeFormat.forStyle("-S").withLocale(Locale.getDefault()).print(roomQuery.getTo()));
				break;
		}
		when.append(')');
		return when.toString();
	}
	
	private String getWhere() {
		RoomQuery roomQuery = getRoomQuery();
		StringBuilder where = new StringBuilder(getResources().getString(R.string.navigation_where));
		where.append(": ");
		switch (roomQuery.getWhere()) {
		case ANYWHERE:
			where.append(getResources().getString(R.string.where_anywhere));
			break;
		case BUILDINGS:
			where.append(getResources().getString(R.string.where_buildings));
			where.append(' ');
			ArrayList<String> buildings = new ArrayList<String>(roomQuery.getBuildings());
			Collections.sort(buildings);
			where.append(StringUtils.join(buildings, ", "));
			break;
		}
		return where.toString();
	}
	
	private String getWhat() {
		RoomQuery roomQuery = getRoomQuery();
		StringBuilder what = new StringBuilder(getResources().getString(R.string.navigation_what));
		if (roomQuery.getOS().size() > 0) {
			what.append(": ");
			List<String> osNames = new ArrayList<String>();
			for (WhatOS os : roomQuery.getOS()) {
				osNames.add(getResources().getString(getResources().getIdentifier("what_os_" + os.name(), "string", getActivity().getPackageName())));
			}
			Collections.sort(osNames);
			for (int i = 0; i < osNames.size() - 1; i++) {
				what.append(osNames.get(i));
				if (i != osNames.size()-2)
					what.append(',');
				what.append(' ');
			}
			if (osNames.size() >= 2) {
				if (roomQuery.getWhat() == What.ANY_OF)
					what.append(getResources().getString(R.string.what_or));
				else 
					what.append(getResources().getString(R.string.what_and));
			}
			what.append(' ');
			what.append(osNames.get(osNames.size() - 1));
		}
		return what.toString();
	}
	
	private String getResults() {
		RoomQuery roomQuery = getRoomQuery();
		StringBuilder results = new StringBuilder(getResources().getString(R.string.navigation_results));
		return results.toString();
	}


	private Button setButtonText(View view, int id, String text) {
		Button button = (Button)view.findViewById(id);
		button.setText(text);
		return button;
	}
	
	@Override
	public void onDestroyView() {
		super.onDestroyView();
		getRoomQuery().deleteObserver(this);
	}

	@Override
	public void onAttach(Activity activity) {
		super.onAttach(activity);

		// Activities containing this fragment must implement its callbacks.
		if (!(activity instanceof NavigationListener)) {
			throw new IllegalStateException(
					"Activity must implement fragment's callbacks.");
		}

		listener = (NavigationListener) activity;
	}

	@Override
	public void onDetach() {
		super.onDetach();
		listener = DUMMY_LISTENER;
	}

	@Override
	public void onSaveInstanceState(Bundle outState) {
		super.onSaveInstanceState(outState);
		if (selectedItem != ListView.INVALID_POSITION) {
			// Serialize and persist the activated item position.
			outState.putInt(STATE_SELECTED_ITEM, selectedItem);
		}
	}	
	
	@Override
	public void update(Observable observable, Object data) {
		setButtonText(getView(), R.id.navigation_when_button, getWhen());
		setButtonText(getView(), R.id.navigation_where_button, getWhere());
		setButtonText(getView(), R.id.navigation_what_button, getWhat());
		setButtonText(getView(), R.id.navigation_results_button, getResults());
	}

	@Override
	public void onClick(View clicked) {
		String id = null;
		
		switch(clicked.getId()) {
			case R.id.navigation_when_button:
				id = NAVIGATION_WHEN;
				break;
			case R.id.navigation_where_button:
				id = NAVIGATION_WHERE;
				break;
			case R.id.navigation_what_button:
				id = NAVIGATION_WHAT;
				break;
			case R.id.navigation_results_button:
				id = NAVIGATION_RESULTS;
				break;
		}
		
		listener.onNavigateToDetail(id);
	}


	public void setIsTwoPane(boolean twoPane) {
		this.twoPane = twoPane;
	}
}
